using System;
using System.Collections;
using System.Web;
using Sedna.Core.Support;
using Spring.Util;

namespace Sedna.Core.Controller
{
	public class WorkflowContext : IWorkflowContext
	{
		private const String SESSION_KEY = "__WORKFLOWCONTEXT";

		private String workflowId;
		private IDictionary context = new Hashtable();

		/// <summary>
		/// Use this way of reception of a context if your page has property WorkflowId.
		/// </summary>
		public static IWorkflowContext Current
		{
			get
			{
				if (BasePage.Current != null)
				{
					return GetInstance(BasePage.Current.WorkflowId);
				}

				return null;
			}
		}

		/// <summary>
		/// Use this way if you need to receive a context with the certain identifier.
		/// </summary>
		public static IWorkflowContext GetInstance(String workflowId)
		{
			if (StringUtils.IsNullOrEmpty(workflowId))
			{
				return null;
			}

			IWorkflowContext workflowContext = (IWorkflowContext)HttpContext.Current.Session[SESSION_KEY];

			if (workflowContext == null || !workflowContext.WorkflowId.Equals(workflowId))
			{
				workflowContext = new WorkflowContext(workflowId);
				HttpContext.Current.Session[SESSION_KEY] = workflowContext;
			}				

			return workflowContext;
		}

		public static bool Exist(String workflowId)
		{
			if (StringUtils.IsNullOrEmpty(workflowId))
			{
				return false;
			}

			IWorkflowContext workflowContext = (IWorkflowContext)HttpContext.Current.Session[SESSION_KEY];

			return (workflowContext != null && workflowContext.WorkflowId.Equals(workflowId));
		}

		public String WorkflowId
		{
			get { return workflowId;}
		}

		#region Private Members

		private WorkflowContext(String workflowId)
		{
			Assert.IsFalse(StringUtils.IsNullOrEmpty(workflowId), "Identifier of the workflow must be not empty and not null");

			this.workflowId = workflowId;
		}

		#endregion

		#region IDictionary Members

		public void CopyTo(Array array, int index)
		{
			context.CopyTo(array, index);
		}

		public int Count
		{
			get { return context.Count;}
		}

		public object SyncRoot
		{
			get { return context.SyncRoot;}
		}		

		public bool IsSynchronized
		{
			get { return context.IsSynchronized;}
		}

		public IDictionaryEnumerator GetEnumerator()
		{
			return context.GetEnumerator();
		}

		public bool Contains(object key)
		{
			return context.Contains(key);
		}

		public void Add(object key, object value)
		{
			context.Add(key, value);
		}

		public void Clear()
		{
			context.Clear();
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return ((IEnumerable)context).GetEnumerator();
		}

		public void Remove(object key)
		{
			context.Remove(key);
		}

		public ICollection Keys
		{
			get { return context.Keys;}
		}

		public ICollection Values
		{
			get { return context.Values;}
		}

		public bool IsReadOnly
		{
			get { return context.IsReadOnly;}
		}

		public bool IsFixedSize
		{
			get { return context.IsFixedSize;}
		}

		public object this[object key]
		{
			get { return context[key];}
			set { context[key] = value;}
		}

		#endregion
	}
}
